home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dlink / final.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-09  |  7.5 KB  |  347 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  FINAL.C
  9.  *
  10.  *  Generate final output
  11.  */
  12.  
  13. #include "defs.h"
  14.  
  15. #define HEAD    0x48454144
  16. #define DBGV    0x44424756
  17.  
  18. Prototype void    GenerateFinalExecutable(FILE *, List *);
  19. Prototype short ForceSym(Sym *);
  20.  
  21. void
  22. GenerateFinalExecutable(fo, list)
  23. FILE *fo;
  24. List *list;
  25. {
  26.     HunkListNode *hl;
  27.     Hunk *hunk;
  28.     int i;
  29.     long nhunk_debug = 0;   /*    debug hunks */
  30.     long nhunk_symd0 = 0;   /*    symbol hunks with no associated debug hunks */
  31.     long nhunk_symd1 = 0;   /*    symbol hunks with associated debug hunks    */
  32.     long headdb_seek = 0;
  33.  
  34.     putl(fo, 0x3F3);        /*    hunk_hdr    */
  35.     putl(fo, 0);        /*    no name     */
  36.     putl(fo, NumExtHunks);  /*    table size  */
  37.     putl(fo, 0);        /*    first hunk  */
  38.     putl(fo, NumExtHunks-1);/*    last hunk   */
  39.  
  40.     for (hl = GetHead(list); hl; hl = GetSucc(&hl->Node)) {
  41.     long mask = (hl->HunkId & 0xFFFF0000) & ~HUNKIDF_FLAG;
  42.  
  43.     if (ChipOpt) {
  44.         mask &= ~0x80000000;
  45.         mask |= 0x40000000;
  46.     }
  47.     if (ResOpt)
  48.         putl(fo, mask | (hl->FinalSize >> 2));
  49.     else
  50.         putl(fo, mask | ((hl->FinalSize + hl->AddSize) >> 2));
  51.     }
  52.  
  53.     /*
  54.      *    If debugging is enabled (-d), include the master debug hunk
  55.      *    required by CPR
  56.      */
  57.  
  58.     if (DebugOpt) {
  59.     long lw = 8 + 3;    /*    8 lw of hdr, 3 lw of sub hdr    */
  60.     long nsymd0 = 0;
  61.     long nsymd1 = 0;
  62.     long max_array = 0;
  63.  
  64.     for (hl = GetHead(list); hl; hl = GetSucc(&hl->Node)) {
  65.         short havesyms = 0;
  66.         short havedebug = 0;
  67.  
  68.         for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
  69.         if (hunk->DbInfo) {
  70.             ++lw;   /*    number of debug hunks    */
  71.             ++nhunk_debug;
  72.             havedebug = 1;
  73.         }
  74.         }
  75.         {
  76.         Sym *sym;
  77.  
  78.         for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
  79.             for (sym = GetHead(&hunk->SymList); sym; sym = GetSucc((Node *)&sym->Node)) {
  80.             if (sym->Type == 1) {
  81.                 if (havesyms == 0) {
  82.                 if (havedebug)
  83.                     ++nhunk_symd1;
  84.                 else
  85.                     ++nhunk_symd0;
  86.                 ++lw;
  87.                 havesyms = 1;
  88.                 }
  89.                 if (havedebug)
  90.                 ++nsymd1;
  91.                 else
  92.                 ++nsymd0;
  93.             }
  94.             }
  95.         }
  96.         }
  97.     }
  98.  
  99.     if ((max_array = nhunk_debug) < nhunk_symd0)
  100.         max_array = nhunk_symd0;
  101.     if (max_array < nhunk_symd1)
  102.         max_array = nhunk_symd1;
  103.  
  104.     putl(fo, 0x3F1);
  105.     putl(fo, lw-2);
  106.     putl(fo, max_array);
  107.     putl(fo, HEAD);
  108.     putl(fo, DBGV);
  109.     putl(fo, 0x30310000);
  110.     putl(fo, nsymd0);
  111.     putl(fo, nsymd1);
  112.     headdb_seek = ftell(fo);
  113.     for (lw = lw - 8; lw; --lw)
  114.         putl(fo, 0);
  115.     }
  116.  
  117.     /*
  118.      *    MAIN BODY
  119.      */
  120.  
  121.     for (hl = GetHead(list); hl; hl = GetSucc(&hl->Node)) {
  122.     long mask = (hl->HunkId & 0xFFFF0000) & ~HUNKIDF_FLAG;
  123.  
  124.     if (ChipOpt) {
  125.         mask &= ~0x80000000;
  126.         mask |= 0x40000000;
  127.     }
  128.  
  129.     /*
  130.      *  output HUNK_CODE, DATA, or BSS
  131.      */
  132.  
  133.     switch(hl->Node.ln_Type) {
  134.     case NT_BSS:
  135.         putl(fo, 0x3EB | mask);
  136.         break;
  137.     case NT_CODE:
  138.         putl(fo, 0x3E9 | mask);
  139.         break;
  140.     case NT_DATA:
  141.         putl(fo, 0x3EA | mask);
  142.         break;
  143.     }
  144.  
  145.     putl(fo, hl->FinalSize >> 2);
  146.  
  147.     /*
  148.      *  if not BSS output the code/data
  149.      */
  150.  
  151.     if (hl->Node.ln_Type == NT_DATA || hl->Node.ln_Type == NT_CODE) {
  152.         long n = 0;
  153.  
  154.         for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
  155.         if (hunk->Node.ln_Type == NT_BSS)
  156.             continue;
  157.         fwrite((char *)hunk->Data, 1, hunk->Bytes, fo);
  158.  
  159.         /*
  160.          *  Generate jump table
  161.          */
  162.  
  163.         if (hunk->TotalBytes != hunk->Bytes) {
  164.             dbprintf(0, ("WRITE %d bytes of jump table\n", hunk->TotalBytes - hunk->Bytes));
  165.             fwrite((char *)hunk->JmpData, 1, (hunk->TotalBytes - hunk->Bytes + 3) & ~3, fo);
  166.         }
  167.         n += (hunk->TotalBytes + 3) & ~3;
  168.         }
  169.         if (n != hl->FinalSize)
  170.         cerror(EFATAL_FINAL_SIZE_MISMATCH, n, hl->FinalSize);
  171.     }
  172. #ifdef MINIDICE
  173.     if (ftell(fo) / 23 >= (40000 + 22) / 23)
  174.         cerror(EFATAL_EXECUTABLE_TOO_LARGE);
  175. #endif
  176.  
  177.     /*
  178.      *  If there is any relocation information output that
  179.      */
  180.  
  181.     for (i = 0; i < NumExtHunks; ++i) {
  182.         if (hl->CntReloc32[i])
  183.         break;
  184.     }
  185.     if (i < NumExtHunks) {        /*  at least one    */
  186.         HunkListNode *hl2 = GetHead(list);
  187.  
  188.         if (PIOpt)
  189.         cerror(EERROR_RELOC32_ILLEGAL_PI_NH);
  190.  
  191.         putl(fo, 0x3EC);        /*  HUNK_RELOC32    */
  192.         for (i = 0; i < NumExtHunks; ++i) {
  193.         long n;
  194.  
  195.         if ((n = hl->CntReloc32[i]) != 0) {
  196.             if (ResOpt && !AbsWordOpt && hl->Node.ln_Type != NT_CODE && hl2->Node.ln_Type != NT_CODE)
  197.             cerror(EERROR_RELOC32_DATA_DATA_RES);
  198.             if (hl->CpyReloc32[i] != n)
  199.             cerror(EFATAL_RELOC_ARRAY_MISMATCH, hl->CpyReloc32[i], n);
  200.  
  201.             putl(fo, n);    /*  n relocs to     */
  202.             putl(fo, i);    /*  hunk # i        */
  203.             fwrite((char *)hl->ExtReloc32[i], 4, n, fo);
  204.             if (PIOpt)
  205.             printf(" 32 bit reloc hunk %ld:$%lx to hunk %d\n", hl->FinalHunkNo, hl->ExtReloc32[i][0], i);
  206.  
  207. #ifdef DEBUG
  208.             if (DDebug > 5) {
  209.             long j;
  210.             for (j = 0; j < n; ++j)
  211.                 printf(" -- reloc h %d offset %08lx\n", i, hl->ExtReloc32[i][j]);
  212.             }
  213. #endif
  214.         }
  215.         hl2 = GetSucc(&hl2->Node);
  216.         }
  217.         putl(fo, 0);
  218.     }
  219.  
  220.     /*
  221.      *  If symbols are enabled dump them
  222.      */
  223.  
  224.     {
  225.         Sym *sym;
  226.  
  227.         for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
  228.         for (sym = GetHead(&hunk->SymList); sym; sym = GetSucc((Node *)&sym->Node)) {
  229.             if (sym->Type == 1 && (SymOpt || (sym->SymLen == 5 && ForceSym(sym))))
  230.             break;
  231.         }
  232.         if (sym)
  233.             break;
  234.         }
  235.         if (hunk) {
  236.         hl->SeekSym = ftell(fo);
  237.         putl(fo, 0x3F0);    /*    HUNK_SYMBOL */
  238.         for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
  239.             for (sym = GetHead(&hunk->SymList); sym; sym = GetSucc((Node *)&sym->Node)) {
  240.             if (sym->Type == 1 && (SymOpt || (sym->SymLen == 5 && ForceSym(sym)))) {
  241.                 long sl = (sym->SymLen + 3) >> 2;    /*  # lws   */
  242.  
  243.                 putl(fo, sl);
  244.                 fwrite(sym->SymName, 4, sl, fo);
  245.  
  246.                 putl(fo, sym->Value + hunk->Offset);
  247.             }
  248.             }
  249.         }
  250.         putl(fo, 0);
  251.         }
  252.     }
  253.  
  254.     /*
  255.      *  If debugging is enabled (-d), include that
  256.      */
  257.  
  258.     if (DebugOpt) {
  259.         for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
  260.         DBInfo *dbinfo;
  261.  
  262.         if ((dbinfo = hunk->DbInfo) == NULL)
  263.             continue;
  264.         dbinfo->di_Base = ToMsbOrder(hunk->Offset);
  265.         hunk->SeekDebug = ftell(fo);
  266.         fwrite(dbinfo, 4, dbinfo->di_Size + 2, fo);
  267.         }
  268.     }
  269.  
  270.     /*
  271.      *  HUNK_END
  272.      */
  273.  
  274.     putl(fo, 0x3F2);
  275.     }
  276.  
  277.     /*
  278.      *    DEBUG MASTER HEADER (CPR SUPPORT)
  279.      */
  280.  
  281.     if (DebugOpt) {
  282.     fseek(fo, headdb_seek, 0);
  283.  
  284.     putl(fo, nhunk_debug);
  285.     for (hl = GetHead(list); hl; hl = GetSucc(&hl->Node)) {
  286.         for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
  287.         if (hunk->DbInfo)
  288.             putl(fo, (hl->FinalHunkNo << 24) | hunk->SeekDebug);
  289.         }
  290.     }
  291.  
  292.     putl(fo, nhunk_symd0);
  293.     if (SymOpt) {
  294.         for (hl = GetHead(list); hl; hl = GetSucc(&hl->Node)) {
  295.         short havedebug = 0;
  296.         for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
  297.             if (hunk->DbInfo) {
  298.             havedebug = 1;
  299.             break;
  300.             }
  301.         }
  302.         if (hl->SeekSym && havedebug == 0) {
  303.             putl(fo, (hl->FinalHunkNo << 24) | hl->SeekSym);
  304.         }
  305.         }
  306.     }
  307.  
  308.     putl(fo, nhunk_symd1);
  309.  
  310.     if (SymOpt) {
  311.         for (hl = GetHead(list); hl; hl = GetSucc(&hl->Node)) {
  312.         short havedebug = 0;
  313.         for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
  314.             if (hunk->DbInfo) {
  315.             havedebug = 1;
  316.             break;
  317.             }
  318.         }
  319.         if (hl->SeekSym && havedebug == 1) {
  320.             putl(fo, (hl->FinalHunkNo << 24) | hl->SeekSym);
  321.         }
  322.         }
  323.     }
  324.  
  325.     fseek(fo, 0L, 2);
  326.     }
  327. }
  328.  
  329. /*
  330.  *  Force _main, @main, _exit, @exit
  331.  *
  332.  */
  333.  
  334. short
  335. ForceSym(sym)
  336. Sym *sym;
  337. {
  338.     /*if (sym->SymLen == 5)*/ {
  339.     if (strncmp(sym->SymName + 1, "main", 4) == 0)
  340.         return(1);
  341.     if (strncmp(sym->SymName + 1, "exit", 4) == 0)
  342.         return(1);
  343.     }
  344.     return(0);
  345. }
  346.  
  347.